#pragma once
namespace graph
{
   struct graph_t
   {   
      graph_t(std::string file_name, std::ostream& logger);
      graph_id_t get_graph_id() const;
      size_t get_edge_count() const;
      size_t get_vertex_count() const;
      vertex_t const & operator [] (size_t idx) const;
      vertex_t & operator [] (size_t idx);
      vertex_t const & get_vertex_by_id(size_t idx) const;
      vertex_t & get_vertex_by_id(size_t idx);
      std::pair<details::edge_real_t*, details::edge_real_t*> get_vertex_edges(vertex_in_graph_id_t idx) const;
      std::pair<details::edge_real_t*, details::edge_real_t*> get_vertex_in_edges(vertex_in_graph_id_t idx) const;
      //O(V) implimentation
      bool get_nearest_vertex(point_t p, vertex_id_t& result) const;
      //O(1) implementation
      //not continious, to get continious func use graph_view
      bool get_nearest_edges(point_t p, std::vector<edge_t> & result) const;
      details::graph_metadata_t const & get_metadata() const;
      //details::graph_metadata_ptr_t meta_data_vect_;
   private:
      details::graph_storage_model_t* graph_;
      details::graph_finalizer_ptr_t graph_finalizer_;
      details::graph_metadata_ptr_t meta_data_;
   };
   typedef boost::shared_ptr<graph_t> graph_ptr_t;

   
   inline vertex_t& source(edge_t e, graph_t& g);
   inline vertex_t const & source(edge_t const e, graph_t const & g);
   inline vertex_t& target(edge_t e, graph_t& g);
   inline vertex_t const & target(edge_t const e, graph_t const & g);

   template<class G>
   struct graph_traits
   {
      struct some_iterator_t;
      typedef some_iterator_t vertex_iterator;
      typedef some_iterator_t edge_iterator;
      typedef some_iterator_t adj_vertices_iterator;
      typedef some_iterator_t adj_edges_iterator;
      typedef some_iterator_t reverse_adj_vertices_iterator;
      typedef some_iterator_t reverse_adj_edges_iterator;
      struct ERROR_NOT_SUPPORTED_GRAPH_TYPE;
      ERROR_NOT_SUPPORTED_GRAPH_TYPE err;
   };

   namespace details
   {
      struct graph_mutable_t
      {
         graph_inf_t inf_;
         graph_mutable_t(graph_inf_t inf);
         void save_sequential_to_file(std::string& file_name);
         void save_not_sequential_to_file(std::string& file_name);
         
         std::vector<vertex_mutable_t>& get_adj_list();
         vertex_mutable_t& add_vertex(point_t p);
      private:
         void make_sequential(graph_sequential_t** result, size_t& size);
         void make_not_sequential(graph_not_sequential_t** result,
                                  vertex_t** vertices, edge_real_t** edges);
         std::vector<vertex_mutable_t> adj_list_;
      };
      typedef boost::shared_ptr<graph_mutable_t> graph_mutable_ptr_t;
   }
}
